package com.yuzhihao.writejvm.format;

import com.yuzhihao.writejvm.attributes.Attributes;
import com.yuzhihao.writejvm.clazz.*;
import com.yuzhihao.writejvm.constant.ConstantPool;
import com.yuzhihao.writejvm.field.Fields;
import com.yuzhihao.writejvm.intfec.InterfaceInfo;
import com.yuzhihao.writejvm.method.Methods;
import com.yuzhihao.writejvm.read.Parse;

import java.io.DataInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * Class类结构枚举
 *
 * @author yzh
 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.1">
 *     jvm格式</a>
 * @since 2021年11月29日16:07:10
 */
public enum ClassFormatEnum {

    /**
     * 魔法值
     */
    magic(4, Magic.class),
    minor_version(2, MinorVersion.class),
    major_version(2, MajorVersion.class),
    constant_pool_count(2, ConstantPool.class),
    cps(0, ConstantPool.class),
    access_flags(2, AccessFlags.class),
    this_class(2, ThisClass.class),
    super_class(2, SuperClass.class),
    interfaces_count(2, InterfaceInfo.class),
    interfaces(2, InterfaceInfo.class),
    fields_count(2, Fields.class),
    fields(0, Fields.class),
    methods_count(2, Methods.class),
    methods(0, Methods.class),
    attributes_count(2, Attributes.class),
    attributes(0, Attributes.class)
    ;

    /**
     * 类文件所占字节数 0 为动态数据
     */
    private final int b;

    private final Class<?> clazz;

    ClassFormatEnum(int b,Class<?> clazz) {
        this.b = b;
        this.clazz = clazz;
    }

    public Parse parse(DataInputStream dis,ClassInfo ci){
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            constructor.setAccessible(true);
            try {
                if (constructor.getParameterCount() == 0) {
                    Object o = constructor.newInstance();
                    if(o instanceof Parse){
                        Parse parse = (Parse) o;
                        parse.parse(dis, ci);
                        return parse;
                    }
                }
            } catch (InvocationTargetException | IllegalAccessException | InstantiationException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public int getB() {
        return b;
    }

}
